#include <linux/autoconf.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>

#include <linux/kernel.h>       /* printk() */
#include <linux/slab.h>         /* kmalloc() */
#include <linux/fs.h>           /* everything... */
#include <linux/errno.h>        /* error codes */
#include <linux/types.h>        /* size_t */
#include <linux/proc_fs.h>
#include <linux/fcntl.h>        /* O_ACCMODE */
#include <linux/seq_file.h>
#include <linux/cdev.h>

#include <asm/system.h>         /* cli(), *_flags */
#include <asm/uaccess.h>        /* copy_*_user */


int jproc_major = 0;
int jproc_minor = 0;

static void *jproc_seq_start(struct seq_file *s, loff_t *pos)
{
  return *pos;
}

static void *jproc_seq_next(struct seq_file *s, void *v, loff_t *pos)
{
  (*pos)++;
  return *pos;
}

static void *jproc_seq_stop(struct seq_file *s, void *v)
{
  //do nothing , yet
}

static int jproc_seq_show(struct seq_file *s, void *v)
{
  seq_printf(s, "Testing proc file buffer");
  return 0;
}


static struct seq_operations jproc_seq_ops = {
        .start = jproc_seq_start,
        .next  = jproc_seq_next,
        .stop  = jproc_seq_stop,
        .show  = jproc_seq_show
};

static int jproc_proc_open(struct inode *inode, struct file *file)
{
        return seq_open(file, &jproc_seq_ops);
}



static struct file_operations jproc_proc_ops = {
        .owner   = THIS_MODULE,
        .open    = jproc_proc_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
        .release = seq_release
};


static void jproc_remove_proc(void)
{
        /* no problem if it was not registered */
  //        remove_proc_entry("jprocmem", NULL /* parent dir */);
        remove_proc_entry("jprocseq", NULL);
}


static void jproc_create_proc(void)
{
  struct proc_dir_entry *entry;
  //  create_proc_read_entry("jprocmem", 0, NULL, NULL);
  entry = create_proc_entry("jprocseq", 0, NULL);
  if (entry)
    entry->proc_fops = &jproc_proc_ops;
  
}

int jproc_init_module(void)
{
  int result;
  dev_t dev = 0;
  // Forcing dynamic allocation for major and minor numbers.
  result = alloc_chrdev_region(&dev, jproc_minor, 1, "jproc");
  jproc_major = MAJOR(dev);
  jproc_minor = MINOR(dev);
  int devno = MKDEV(jproc_major, jproc_minor);

  if (result < 0)
  {
    printk(KERN_WARNING "jproc: can't get major %d\n", jproc_major);
    return result;
  }

  printk(KERN_WARNING "jproc: allocated devno -> %d", devno);
  jproc_create_proc();
  return 0;
}

void jproc_cleanup_module(void)
{
  jproc_remove_proc();
}



module_init(jproc_init_module);
module_exit(jproc_cleanup_module);

